package librairies.liste.list;

import java.util.NoSuchElementException;

import librairies.liste.interfaces.IIterateur;

/**
 * Iterateur sur une liste DCE
 * 
 * @author mlozach
 * @param <E> type de l'elements dans la liste.
 */
public class IterateurDCE<E extends Comparable<E>> implements IIterateur<E> 
{
    private ListeDC<E> liste;
    private Chainon<E> next;
    private Chainon<E> prev;
    private Chainon<E> elementAccessible;
	
    /**
     * constructeur par recopie.
     * @param l liste d'element.
     */
    IterateurDCE(ListeDCE<E> l) 
    {
    	this.liste = l;
    	this.next = l.getTete();
    	this.prev = null;
    	this.elementAccessible = null;
    }
    		
	@Override
	public E next() throws java.util.NoSuchElementException 
	{
		if(this.liste == null)
		{
			throw new NoSuchElementException(); 		
		}
		
		if(this.prev == this.liste.getQueue())
		{
			throw new NoSuchElementException(); 
		}
		
		if(this.next == this.liste.getQueue())
		{
			this.prev = this.next;
			this.next = null;
			elementAccessible = this.prev;
		}
		
		else
		{
			this.prev = this.next;
			this.next = this.next.getSuivant();
			elementAccessible = this.prev;
		}
			
		return elementAccessible.getValeur();
	}
	
	@Override
	public E previous() throws java.util.NoSuchElementException 
	{
		if(this.liste == null)
		{
			throw new NoSuchElementException(); 	
		}
		
		if(this.next == this.liste.getTete())
		{
			throw new NoSuchElementException(); 
		}
		
		if(this.prev == this.liste.getTete())
		{
			this.next = this.prev;
			this.prev = null;
			
			elementAccessible = this.next;
		}
		
		else
		{
			this.next = this.prev;
			this.prev = this.prev.getPrecedent();

			elementAccessible = this.next;
		}
			
		return elementAccessible.getValeur();
	}
	
	@Override
	public void remove() throws IllegalStateException 
	{
		if(elementAccessible == null)
		{
			throw new IllegalStateException();
		}
		
		if(this.liste.size() == 0)
		{
			return;
		}
		
		else if(elementAccessible.getPrecedent() == null)
		{							
			this.liste.setTete(elementAccessible.getSuivant());
			this.liste.getTete().setPrecedent(null);
			elementAccessible.setSuivant(null);
			elementAccessible = null;
		}

		else if(elementAccessible.getSuivant() == null)
		{
			this.liste.setQueue(elementAccessible.getPrecedent());
			this.liste.getQueue().setSuivant(null);
			elementAccessible.setPrecedent(null);
			elementAccessible = null;
		}

		else
		{
			elementAccessible.getPrecedent().setSuivant(elementAccessible.getSuivant());
			elementAccessible.getSuivant().setPrecedent(elementAccessible.getPrecedent());
			elementAccessible = null;
		}
		
		liste.tailleMoinsUn();
		liste.setCourant(liste.getTete());
		liste.setIndiceCourant(liste.size()==0 ? -1 : 0);
	}
	
	@Override
	public void set(E e) throws IllegalStateException 
	{
		if(elementAccessible == null)
		{
			throw new IllegalStateException();
		}
		
		elementAccessible.setValeur(e);
		elementAccessible = null;
	}

	@Override
	public boolean hasNext() {return (next != null);}
	@Override
	public boolean hasPrevious() {return (prev != null);}}
